from flask import Flask, request, jsonify, send_file, make_response
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from datetime import datetime, timedelta
from functools import wraps
import jwt
import json
import subprocess
import os
import logging
from logging.handlers import RotatingFileHandler
import traceback
from werkzeug.security import generate_password_hash, check_password_hash
import random
import string
from PIL import Image, ImageDraw, ImageFont
import io
import importlib.util
import sys
import math
import time
from faker import Faker
import threading

# 创建Flask应用
app = Flask(__name__)

# 配置日志
logging.basicConfig(level=logging.DEBUG)
file_handler = RotatingFileHandler('app.log', maxBytes=10240, backupCount=10)
file_handler.setFormatter(logging.Formatter(
    '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Flask app startup')

# 配置 CORS
CORS(app, resources={
    r"/*": {
        "origins": ["*"],  # 允许所有来源
        "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "allow_headers": ["Content-Type", "Authorization"],
        "expose_headers": ["Content-Type", "Authorization"],
        "supports_credentials": True,  # 改为True以支持凭证
        "max_age": 3600
    }
})

# 移除之前的CORS预检请求处理器，因为flask-cors已经处理了这部分
@app.before_request
def before_request():
    # 只保留日志记录功能
    if request.path != '/health':
        app.logger.info('Headers: %s', dict(request.headers))
        app.logger.info('Method: %s, Path: %s', request.method, request.path)
        if request.method != 'OPTIONS':
            auth_header = request.headers.get('Authorization')
            if auth_header:
                app.logger.info('Auth header present: %s', auth_header[:20] + '...' if len(auth_header) > 20 else auth_header)
            else:
                app.logger.info('No Authorization header present')

# 移除之前的after_request处理器，避免重复添加CORS头
@app.after_request
def after_request(response):
    return response

# 配置
SECRET_KEY = 'your-secret-key'  # 请更改为安全的密钥
TOKEN_EXPIRATION = timedelta(days=1)

# 配置数据库
# 原始配置使用远程MySQL，但无法连接，所以改用SQLite
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///motor_db.sqlite'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 添加重试机制
def get_db_connection(max_retries=3, retry_delay=1):
    """获取数据库连接，带有重试机制"""
    for attempt in range(max_retries):
        try:
            # 使用更兼容的方式测试数据库连接
            db.session.execute(db.text("SELECT 1"))
            db.session.commit()
            return True
        except Exception as e:
            if attempt == max_retries - 1:
                app.logger.error(f"Database connection failed after {max_retries} attempts: {str(e)}")
                raise
            app.logger.warning(f"Database connection attempt {attempt + 1} failed: {str(e)}")
            time.sleep(retry_delay)
    return False

db = SQLAlchemy(app)

# 添加全局变量用于模拟数据生成
last_update_time = time.time()
phase_offsets = [0, math.pi/2, math.pi, 3*math.pi/2]  # 为四个电机设置不同的相位偏移

# 初始化 Faker
fake = Faker()

# 添加安全范围常量
SAFETY_RANGES = {
    'motor': {
        'temperature': {'min': 20, 'max': 70, 'warning': 60, 'critical': 65},  # 电机温度范围(°C)
        'current': {'min': -10, 'max': 10, 'warning': 8, 'critical': 9},      # 电机电流范围(A)
        'speed': {'min': -10, 'max': 10, 'warning': 8, 'critical': 9},        # 电机速度范围(rad/s)
        'torque': {'min': -20, 'max': 20, 'warning': 15, 'critical': 18}      # 电机扭矩范围(Nm)
    },
    'battery': {
        'level': {'min': 0, 'max': 100, 'warning': 30, 'critical': 20},       # 电池电量范围(%)
        'voltage': {'min': 20, 'max': 28, 'warning': 22, 'critical': 21},     # 电池电压范围(V)
        'temperature': {'min': 0, 'max': 45, 'warning': 40, 'critical': 43}   # 电池温度范围(°C)
    },
    'system': {
        'temperature': {'min': 0, 'max': 60, 'warning': 50, 'critical': 55},  # 系统温度范围(°C)
        'cpu_usage': {'min': 0, 'max': 100, 'warning': 80, 'critical': 90},   # CPU使用率范围(%)
        'memory_usage': {'min': 0, 'max': 100, 'warning': 80, 'critical': 90} # 内存使用率范围(%)
    },
    'gait': {
        'stride_length': {'min': 50, 'max': 300, 'warning': 250, 'critical': 280},  # 步幅范围(mm)
        'step_height': {'min': 20, 'max': 150, 'warning': 120, 'critical': 140},    # 步高范围(mm)
        'time_interval': {'min': 0.1, 'max': 1.0, 'warning': 0.8, 'critical': 0.9}, # 时间间隔范围(s)
        'point_count': {'min': 10, 'max': 2000, 'warning': 1500, 'critical': 1800}  # 点数范围
    },
    'motion': {
        'sway_angle': {'min': 0, 'max': 45, 'warning': 30, 'critical': 40}    # 晃动角度范围(°)
    }
}

def generate_realistic_motor_data():
    """生成更真实的电机数据，包含合理的波动和差异，允许超出安全范围"""
    global last_update_time
    
    current_time = time.time()
    time_diff = current_time - last_update_time
    last_update_time = current_time

    # 基础波动频率（Hz）
    freq = 0.5
    
    # 为每个电机生成不同的数据
    motor_data = {
        'temperatures': [],
        'currents': [],
        'speeds': [],
        'torques': [],
        'positions': [],
        'modes': []
    }

    for i in range(4):
        # 使用时间和相位偏移生成正弦波
        phase = 2 * math.pi * freq * time_diff + phase_offsets[i]
        
        # 温度：允许超出安全范围，最高可达80°C
        temp = 35 + 45 * math.sin(phase * 0.1)  # 范围：-10°C 到 80°C
        motor_data['temperatures'].append(round(temp, 2))
        
        # 电流：允许超出安全范围，最大可达±15A
        current = 15 * math.sin(phase)  # 范围：-15A 到 15A
        motor_data['currents'].append(round(current, 2))
        
        # 速度：允许超出安全范围，最大可达±15rad/s
        speed = 15 * math.sin(phase * 1.2)  # 范围：-15rad/s 到 15rad/s
        motor_data['speeds'].append(round(speed, 2))
        
        # 扭矩：允许超出安全范围，最大可达±25Nm
        torque = 25 * math.sin(phase * 0.8)  # 范围：-25Nm 到 25Nm
        motor_data['torques'].append(round(torque, 2))
        
        # 位置：0-360度范围内波动
        position = 180 + 180 * math.sin(phase * 0.5)
        motor_data['positions'].append(round(position, 2))
        
        # 模式：随机生成不同状态
        modes = ["running", "warning", "error", "standby"]
        motor_data['modes'].append(random.choice(modes))

    return motor_data

def generate_system_data():
    """生成系统相关的模拟数据，允许超出安全范围"""
    # 电池电量：允许低至0%
    battery_level = 50 + 50 * math.sin(time.time() * 0.05)  # 范围：0-100%
    
    # 电池电压：允许超出安全范围
    battery_voltage = 24 + 6 * math.sin(time.time() * 0.1)  # 范围：18-30V
    
    # 电池电流：允许较大波动
    battery_current = 5 * math.sin(time.time() * 0.15)  # 范围：-5A到5A
    
    # 电池温度：允许超出安全范围
    battery_temperature = 30 + 20 * math.sin(time.time() * 0.08)  # 范围：10-50°C
    
    # 系统温度：允许超出安全范围
    system_temperature = 40 + 25 * math.sin(time.time() * 0.12)  # 范围：15-65°C
    
    return {
        'battery_level': round(battery_level, 2),
        'battery_voltage': round(battery_voltage, 2),
        'battery_current': round(battery_current, 2),
        'battery_temperature': round(battery_temperature, 2),
        'temperature': round(system_temperature, 2)
    }

# 身份验证装饰器
def auth_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        auth_header = request.headers.get('Authorization')

        if auth_header:
            try:
                token = auth_header.split(" ")[1]  # Bearer <token>
            except IndexError:
                return jsonify({'message': 'Invalid token format'}), 401

        if not token:
            app.logger.warning("No token provided")
            return jsonify({'message': 'Token is missing'}), 401

        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
            user_id = payload['sub']
            # 将字符串ID转回整数
            user_id = int(user_id)
            return f(user_id, *args, **kwargs)
        except jwt.ExpiredSignatureError:
            app.logger.warning("Token has expired")
            return jsonify({'message': 'Token has expired'}), 401
        except jwt.InvalidTokenError as e:
            app.logger.warning(f"Invalid token: {str(e)}")
            return jsonify({'message': 'Invalid token'}), 401
        except Exception as e:
            app.logger.error(f"Auth error: {str(e)}")
            return jsonify({'message': 'Authentication failed'}), 401

    return decorated

# 管理员权限检查装饰器
def admin_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        auth_header = request.headers.get('Authorization')

        if auth_header:
            try:
                token = auth_header.split(" ")[1]  # Bearer <token>
            except IndexError:
                return jsonify({'message': 'Invalid token format'}), 401

        if not token:
            app.logger.warning("No token provided")
            return jsonify({'message': 'Token is missing'}), 401

        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
            user_id = int(payload['sub'])
            is_admin = payload.get('is_admin', False)

            if not is_admin:
                app.logger.warning(f"Non-admin user {user_id} attempting admin action")
                return jsonify({'message': 'Admin privileges required'}), 403

            return f(user_id, *args, **kwargs)
        except jwt.ExpiredSignatureError:
            app.logger.warning("Token has expired")
            return jsonify({'message': 'Token has expired'}), 401
        except jwt.InvalidTokenError as e:
            app.logger.warning(f"Invalid token: {str(e)}")
            return jsonify({'message': 'Invalid token'}), 401
        except Exception as e:
            app.logger.error(f"Auth error: {str(e)}")
            return jsonify({'message': 'Authentication failed'}), 401

    return decorated

# 全局错误处理
@app.errorhandler(Exception)
def handle_error(error):
    app.logger.error(f"Unhandled error: {str(error)}")
    app.logger.error(traceback.format_exc())
    return jsonify({
        'message': '服务器内部错误',
        'error': str(error)
    }), 500

@app.errorhandler(404)
def not_found_error(error):
    return jsonify({
        'message': '请求的资源不存在'
    }), 404

# 健康检查端点
@app.route('/health', methods=['GET'])
def health_check():
    try:
        # 测试数据库连接
        with app.app_context():
            db.engine.connect()
        return jsonify({
            'status': 'ok',
            'message': 'Server is running and database is connected',
            'timestamp': datetime.utcnow().isoformat()
        })
    except Exception as e:
        app.logger.error(f"Health check failed: {str(e)}")
        return jsonify({
            'status': 'error',
            'message': str(e),
            'timestamp': datetime.utcnow().isoformat()
        }), 500

# 数据库模型
class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    password = db.Column(db.String(255), nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    is_admin = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    last_login = db.Column(db.DateTime)  # 添加最后登录时间字段

class RobotStatus(db.Model):
    __tablename__ = 'robot_status'
    id = db.Column(db.Integer, primary_key=True)
    battery_level = db.Column(db.Float, nullable=False)  # 电池电量
    battery_voltage = db.Column(db.Float, nullable=False, default=24.0)  # 电池电压
    battery_current = db.Column(db.Float, nullable=False, default=0.0)  # 电池电流
    battery_temperature = db.Column(db.Float, nullable=False, default=25.0)  # 电池温度
    temperature = db.Column(db.Float, nullable=False)    # 系统温度
    motor_temperatures = db.Column(db.JSON, nullable=False, default=lambda: [25.0, 25.0, 25.0, 25.0])  # 四个电机的温度
    motor_currents = db.Column(db.JSON, nullable=False, default=lambda: [0.0, 0.0, 0.0, 0.0])  # 四个电机的电流
    motor_positions = db.Column(db.JSON, nullable=False, default=lambda: [0.0, 0.0, 0.0, 0.0])  # 四个电机的位置
    motor_speeds = db.Column(db.JSON, nullable=False, default=lambda: [0.0, 0.0, 0.0, 0.0])  # 四个电机的速度
    motor_torques = db.Column(db.JSON, nullable=False, default=lambda: [0.0, 0.0, 0.0, 0.0])  # 四个电机的扭矩
    motor_modes = db.Column(db.JSON, nullable=False, default=lambda: ["standby", "standby", "standby", "standby"])  # 四个电机的工作模式
    imu_data = db.Column(db.JSON, nullable=False, default=lambda: {"acc": [0.0, 0.0, 0.0], "gyro": [0.0, 0.0, 0.0]})  # IMU数据
    running_status = db.Column(db.String(50), nullable=False)  # 运行状态
    gps_latitude = db.Column(db.Float)  # GPS纬度
    gps_longitude = db.Column(db.Float)  # GPS经度
    cpu_usage = db.Column(db.Float)  # CPU使用率
    memory_usage = db.Column(db.Float)  # 内存使用率
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    status_data = db.Column(db.JSON, nullable=False, default=lambda: {})  # 添加status_data字段

class MotionControl(db.Model):
    __tablename__ = 'motion_control'
    id = db.Column(db.Integer, primary_key=True)
    gait_type = db.Column(db.String(50), nullable=False)  # 步态类型
    speed = db.Column(db.Float, nullable=False)  # 速度
    direction = db.Column(db.String(50), nullable=False)  # 方向
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class Alert(db.Model):
    __tablename__ = 'alert'
    id = db.Column(db.Integer, primary_key=True)
    type = db.Column(db.String(50), nullable=False)  # 告警类型
    level = db.Column(db.String(50), nullable=False)  # 告警级别
    message = db.Column(db.Text, nullable=False)  # 告警信息
    status = db.Column(db.String(50), nullable=False)  # 处理状态
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class FileData(db.Model):
    __tablename__ = 'file_data'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    log_content = db.Column(db.Text, nullable=False)
    data_content = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class GaitData(db.Model):
    """步态数据模型"""
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    task_id = db.Column(db.String(50), nullable=False)
    stride_length = db.Column(db.Float, nullable=False)
    step_height = db.Column(db.Float, nullable=False)
    time_interval = db.Column(db.Float, nullable=False)
    point_count = db.Column(db.Integer, nullable=False)
    result = db.Column(db.String(10), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    def to_dict(self):
        return {
            'id': self.id,
            'user_id': self.user_id,
            'task_id': self.task_id,
            'stride_length': self.stride_length,
            'step_height': self.step_height,
            'time_interval': self.time_interval,
            'point_count': self.point_count,
            'result': self.result,
            'created_at': self.created_at.isoformat()
        }

class NewModel(db.Model):
    __tablename__ = 'new_model'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    name = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

# 安全锁模型
class SafetyLock(db.Model):
    __tablename__ = 'safety_lock'
    id = db.Column(db.Integer, primary_key=True)
    max_motor_temp = db.Column(db.Float, nullable=False, default=45.0)
    max_cpu_usage = db.Column(db.Float, nullable=False, default=80.0)
    max_memory_usage = db.Column(db.Float, nullable=False, default=90.0)
    max_sway_angle = db.Column(db.Float, nullable=False, default=30.0)
    min_battery_level = db.Column(db.Float, nullable=False, default=20.0)
    max_stride_length = db.Column(db.Float, nullable=False, default=100.0)
    max_step_height = db.Column(db.Float, nullable=False, default=50.0)
    min_time_interval = db.Column(db.Float, nullable=False, default=0.1)
    max_point_count = db.Column(db.Integer, nullable=False, default=1000)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

class Task(db.Model):
    __tablename__ = 'task'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    type = db.Column(db.String(50), nullable=False)
    status = db.Column(db.String(50), nullable=False)
    start_time = db.Column(db.DateTime, default=datetime.utcnow)
    end_time = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

# 设备模型
class Device(db.Model):
    __tablename__ = 'device'
    id = db.Column(db.String(50), primary_key=True)
    model = db.Column(db.String(100), nullable=False)
    firmware_version = db.Column(db.String(50), nullable=False)
    location = db.Column(db.String(200))
    is_connected = db.Column(db.Boolean, default=False)
    motor_status = db.Column(db.JSON, default=lambda: ["normal", "normal", "normal", "normal"])
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class DeviceBinding(db.Model):
    __tablename__ = 'device_binding'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    device_id = db.Column(db.String(50), db.ForeignKey('device.id'), nullable=False)
    bind_time = db.Column(db.DateTime, default=datetime.utcnow)

# 注册接口
@app.route('/register', methods=['POST'])
def register():
    try:
        app.logger.info('Received registration request')
        data = request.get_json()
        app.logger.debug(f'Registration data: {data}')
        
        if not data:
            app.logger.error('No JSON data received')
            return jsonify({'message': 'No data provided'}), 400
            
        username = data.get('username')
        password = data.get('password')
        email = data.get('email')
        is_admin = data.get('is_admin', False)
        
        app.logger.info(f"Parsed registration data - username: {username}, email: {email}, is_admin: {is_admin}")
        
        if not all([username, password, email]):
            app.logger.warning("Registration failed: Missing required fields")
            return jsonify({'message': '用户名、密码和邮箱都是必填项'}), 400

        # 检查用户名是否已存在
        existing_user = User.query.filter_by(username=username).first()
        if existing_user:
            app.logger.warning(f"Registration failed: Username {username} already exists")
            return jsonify({'message': '用户名已存在'}), 400

        # 检查邮箱是否已存在
        existing_email = User.query.filter_by(email=email).first()
        if existing_email:
            app.logger.warning(f"Registration failed: Email {email} already exists")
            return jsonify({'message': '邮箱已被注册'}), 400

        # 创建新用户
        hashed_password = generate_password_hash(password)
        new_user = User(
            username=username,
            password=hashed_password,
            email=email,
            is_admin=is_admin
        )

        app.logger.info(f"Attempting to add new user: {username}")
        db.session.add(new_user)
        db.session.commit()
        app.logger.info(f"Registration successful for user: {username}")
        return jsonify({'message': '注册成功'}), 201
        
    except Exception as e:
        db.session.rollback()
        app.logger.error(f"Registration error: {str(e)}")
        app.logger.error(traceback.format_exc())
        return jsonify({'message': f'注册失败: {str(e)}'}), 500

# 登录接口
@app.route('/login', methods=['POST'])
def login():
    try:
        app.logger.info("Received login request")
        data = request.get_json()
        
        if not data:
            app.logger.warning("Login failed: No JSON data received")
            return jsonify({'message': '请求数据不能为空'}), 400
            
        app.logger.info(f"Login data received: {json.dumps(data, ensure_ascii=False)}")
        
        username = data.get('username')
        password = data.get('password')
        user_type = data.get('userType', 'user')  # 默认为普通用户
        
        app.logger.info(f"Login attempt for user: {username}, type: {user_type}")
        
        if not username or not password:
            app.logger.warning("Login failed: Missing username or password")
            return jsonify({'message': '用户名和密码不能为空'}), 400

        try:
            # 使用重试机制检查数据库连接
            if not get_db_connection():
                return jsonify({'message': '数据库连接失败，请稍后重试'}), 500
        except Exception as e:
            app.logger.error(f"Database connection error: {str(e)}")
            return jsonify({'message': '数据库连接失败，请稍后重试'}), 500

        try:
            user = User.query.filter_by(username=username).first()
        except Exception as e:
            app.logger.error(f"Error querying user: {str(e)}")
            return jsonify({'message': '查询用户信息失败，请稍后重试'}), 500
        
        if not user or not check_password_hash(user.password, password):
            app.logger.warning(f"Login failed: Invalid credentials for user {username}")
            return jsonify({'message': '用户名或密码错误'}), 401

        # 验证用户类型
        if user_type == 'admin' and not user.is_admin:
            app.logger.warning(f"Login failed: Non-admin user {username} attempting admin login")
            return jsonify({'message': '权限不足'}), 403
        elif user_type == 'user' and user.is_admin:
            app.logger.warning(f"Login failed: Admin user {username} attempting regular user login")
            return jsonify({'message': '请使用管理员登录入口'}), 403
        
        # 更新最后登录时间
        try:
            user.last_login = datetime.utcnow()
            db.session.commit()
        except Exception as e:
            app.logger.error(f"Failed to update last login time: {str(e)}")
            db.session.rollback()
            # 继续执行，不影响登录流程
        
        # 创建JWT payload
        exp_time = datetime.utcnow() + TOKEN_EXPIRATION
        payload = {
            'sub': str(user.id),
            'is_admin': user.is_admin,
            'username': user.username,
            'exp': exp_time,
            'iat': datetime.utcnow()
        }
        
        try:
            token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
            
            if isinstance(token, bytes):
                token = token.decode('utf-8')
            
            response_data = {
                'token': token,
                'is_admin': user.is_admin,
                'username': user.username,
                'message': '登录成功',
                'permissions': {
                    'can_generate_gait': not user.is_admin,
                    'can_view_analytics': user.is_admin,
                    'can_set_safety_locks': user.is_admin,
                    'can_manage_users': user.is_admin
                }
            }
            
            return jsonify(response_data), 200
        except Exception as e:
            app.logger.error(f"Token generation error: {str(e)}")
            return jsonify({'message': '生成登录令牌失败'}), 500

    except Exception as e:
        app.logger.error(f"Login error: {str(e)}")
        app.logger.error(traceback.format_exc())
        return jsonify({'message': f'登录失败: {str(e)}'}), 500

# 上传文件接口
@app.route('/upload_files', methods=['POST'])
@auth_required
def upload_files(user_id):
    data = request.get_json()
    log_content = data.get('log_content')
    coordinates = data.get('coordinates')
    if not log_content or not coordinates:
        return jsonify({'message': 'log_content and coordinates are required'}), 400
    # 直接使用坐标列表，不需要 Base64 解码
    data_content = json.dumps(coordinates)
    file_data = FileData(
        user_id=user_id,
        log_content=log_content,
        data_content=data_content
    )
    db.session.add(file_data)
    db.session.commit()
    return jsonify({'message': 'Files uploaded successfully'}), 200

# 刷新数据接口
@app.route('/refresh_data', methods=['GET'])
@auth_required
def refresh_data(user_id):
    app.logger.info(f"Refreshing data for user {user_id}")
    try:
        # 查询当前用户的所有步态数据
        gait_data_list = GaitData.query.filter_by(user_id=user_id).order_by(GaitData.created_at.desc()).all()
        app.logger.info(f"Found {len(gait_data_list)} records for user {user_id}")
        
        result = []
        for gait_data in gait_data_list:
            result.append({
                'id': gait_data.id,
                'task_id': gait_data.task_id,
                'stride_length': gait_data.stride_length,
                'step_height': gait_data.step_height,
                'time_interval': gait_data.time_interval,
                'point_count': gait_data.point_count,
                'result': gait_data.result,
                'created_at': gait_data.created_at.strftime('%Y-%m-%d %H:%M:%S')
            })
        
        app.logger.info(f"Returning {len(result)} records")
        return jsonify({'success': True, 'data': result}), 200
    except Exception as e:
        app.logger.error(f"Refresh data error: {str(e)}")
        app.logger.error(traceback.format_exc())
        return jsonify({'success': False, 'message': f'刷新数据失败: {str(e)}'}), 500

# 服务器端代码（部分）
@app.route('/api/admin/generate_gait', methods=['POST'])
@auth_required
def generate_gait(user_id):
    """生成步态数据"""
    try:
        data = request.get_json()
        if not data or 'taskId' not in data:
            return jsonify({'message': '缺少任务ID'}), 400

        task_id = data['taskId']
        
        # 获取当前文件所在目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        script_path = os.path.join(current_dir, f"task_{task_id}.py")
        
        if not os.path.exists(script_path):
            return jsonify({'message': f'任务脚本不存在: task_{task_id}.py'}), 404

        try:
            # 动态导入任务模块
            module_name = f"task_{task_id}"
            if module_name in sys.modules:
                del sys.modules[module_name]
            
            spec = importlib.util.spec_from_file_location(module_name, script_path)
            task_module = importlib.util.module_from_spec(spec)
            sys.modules[module_name] = task_module
            spec.loader.exec_module(task_module)
            
            # 执行任务
            result = task_module.generate_random_data()
            
            # 创建步态数据对象
            gait_data = GaitData(
                user_id=user_id,
                task_id=task_id,
                stride_length=float(result['d']),
                step_height=float(result['h']),
                time_interval=float(result['t']),
                point_count=int(result['n']),
                result=result['result']
            )

            # 保存到数据库
            db.session.add(gait_data)
            db.session.commit()

            return jsonify({
                'success': True,
                'message': '步态数据生成成功',
                'output': {
                    '步幅d': result['d'],
                    '步高h': result['h'],
                    '时间间隔t': result['t'],
                    '点数n': result['n'],
                    '结果result': result['result']
                }
            }), 200

        except Exception as e:
            app.logger.error(f"任务执行失败: {str(e)}")
            return jsonify({'message': f'任务执行失败: {str(e)}'}), 500

    except Exception as e:
        app.logger.error(f"生成步态数据失败: {str(e)}")
        return jsonify({'message': f'生成步态数据失败: {str(e)}'}), 500

# 查询步态数据接口
@app.route('/query_gait_data', methods=['GET'])
@auth_required
def query_gait_data(user_id):
    app.logger.info(f"Querying gait data for user {user_id}")
    try:
        # 查询当前用户的所有步态数据
        gait_data_list = GaitData.query.filter_by(user_id=user_id).all()
        app.logger.info(f"Found {len(gait_data_list)} records for user {user_id}")
        
        result = []
        for gait_data in gait_data_list:
            result.append({
                'id': gait_data.id,
                'task_id': gait_data.task_id,
                'stride_length': gait_data.stride_length,
                'step_height': gait_data.step_height,
                'time_interval': gait_data.time_interval,
                'point_count': gait_data.point_count,
                'result': gait_data.result,
                'created_at': gait_data.created_at.strftime('%Y-%m-%d %H:%M:%S')
            })
        
        app.logger.info(f"Returning {len(result)} records")
        return jsonify({'success': True, 'data': result}), 200
    except Exception as e:
        app.logger.error(f"Query error: {str(e)}")
        app.logger.error(traceback.format_exc())
        return jsonify({'success': False, 'message': f'获取数据失败: {str(e)}'}), 500

# 管理员获取所有用户数据
@app.route('/api/admin/users', methods=['GET'])
@admin_required
def get_all_users(user_id):
    try:
        app.logger.info(f"Admin {user_id} requesting all users data")
        users = User.query.all()
        users_data = [{
            'id': user.id,
            'username': user.username,
            'email': user.email,
            'is_admin': user.is_admin,
            'created_at': user.created_at.strftime('%Y-%m-%d %H:%M:%S')
        } for user in users]
        app.logger.info(f"Returning {len(users_data)} users")
        return jsonify(users_data)
    except Exception as e:
        app.logger.error(f"Error in get_all_users: {str(e)}")
        return jsonify({'message': str(e)}), 500

@app.route('/api/admin/user/<int:target_user_id>', methods=['DELETE'])
@admin_required
def delete_user(user_id, target_user_id):
    try:
        user = User.query.get(target_user_id)
        if not user:
            return jsonify({'message': 'User not found'}), 404
        db.session.delete(user)
        db.session.commit()
        return jsonify({'message': 'User deleted successfully'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'message': str(e)}), 500

@app.route('/api/admin/user', methods=['POST'])
@admin_required
def create_user(user_id):
    try:
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')
        is_admin = data.get('is_admin', False)

        if not username or not password:
            return jsonify({'message': 'Username and password are required'}), 400

        if User.query.filter_by(username=username).first():
            return jsonify({'message': 'Username already exists'}), 400

        hashed_password = generate_password_hash(password)
        new_user = User(username=username, password=hashed_password, is_admin=is_admin)
        db.session.add(new_user)
        db.session.commit()

        return jsonify({
            'id': new_user.id,
            'username': new_user.username,
            'is_admin': new_user.is_admin
        }), 201
    except Exception as e:
        db.session.rollback()
        return jsonify({'message': str(e)}), 500

# 管理员获取所有步态数据
@app.route('/api/admin/gait_data', methods=['GET'])
@admin_required
def get_all_gait_data(user_id):
    try:
        app.logger.info(f"Admin {user_id} requesting all gait data")
        gait_data = GaitData.query.all()
        data = [{
            'id': data.id,
            'username': User.query.get(data.user_id).username if User.query.get(data.user_id) else 'Unknown',
            'task_id': data.task_id,
            'stride_length': data.stride_length,
            'step_height': data.step_height,
            'time_interval': data.time_interval,
            'point_count': data.point_count,
            'result': data.result,
            'created_at': data.created_at.strftime('%Y-%m-%d %H:%M:%S')
        } for data in gait_data]
        app.logger.info(f"Returning {len(data)} gait records")
        return jsonify(data)
    except Exception as e:
        app.logger.error(f"Error in get_all_gait_data: {str(e)}")
        return jsonify({'message': str(e)}), 500

# 管理员获取所有文件数据
@app.route('/api/admin/file_data', methods=['GET'])
@admin_required
def get_all_file_data(user_id):
    try:
        app.logger.info(f"Admin {user_id} requesting all file data")
        file_data = FileData.query.all()
        data = [{
            'id': data.id,
            'username': User.query.get(data.user_id).username if User.query.get(data.user_id) else 'Unknown',
            'log_content': data.log_content,
            'data_content': data.data_content,
            'created_at': data.created_at.strftime('%Y-%m-%d %H:%M:%S')
        } for data in file_data]
        app.logger.info(f"Returning {len(data)} file records")
        return jsonify(data)
    except Exception as e:
        app.logger.error(f"Error in get_all_file_data: {str(e)}")
        return jsonify({'message': str(e)}), 500

@app.route('/api/verify_token', methods=['GET'])
def verify_token():
    token = None
    auth_header = request.headers.get('Authorization')

    if auth_header:
        try:
            token = auth_header.split(" ")[1]  # Bearer <token>
        except IndexError:
            return jsonify({'message': 'Invalid token format'}), 401

    if not token:
        return jsonify({'message': 'Token is missing'}), 401

    try:
        # 验证token
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        user_id = payload['sub']
        is_admin = payload.get('is_admin', False)
        
        # 检查用户是否存在
        user = User.query.get(int(user_id))
        if not user:
            return jsonify({'message': 'User not found'}), 401
            
        return jsonify({
            'valid': True,
            'user_id': user_id,
            'is_admin': is_admin,
            'username': user.username
        })
    except jwt.ExpiredSignatureError:
        return jsonify({'message': 'Token has expired'}), 401
    except jwt.InvalidTokenError:
        return jsonify({'message': 'Invalid token'}), 401
    except Exception as e:
        app.logger.error(f"Token verification error: {str(e)}")
        return jsonify({'message': 'Token verification failed'}), 401

# 修改机器人状态API路径
@app.route('/api/robot/status', methods=['GET'])
@auth_required
def get_robot_status(user_id):
    """统一的机器人状态API，根据用户类型返回不同的数据"""
    try:
        # 生成模拟数据
        motor_data = generate_realistic_motor_data()
        system_data = generate_system_data()
        
        # 生成IMU数据
        imu_data = {
            'acc': [
                round(random.uniform(-1, 1), 2),
                round(random.uniform(-1, 1), 2),
                round(random.uniform(-9.8, -9.6), 2)  # 考虑重力加速度
            ],
            'gyro': [
                round(random.uniform(-0.1, 0.1), 2),
                round(random.uniform(-0.1, 0.1), 2),
                round(random.uniform(-0.1, 0.1), 2)
            ]
        }
        
        # 生成CPU和内存使用率
        cpu_usage = 20 + 10 * math.sin(time.time() * 0.1)
        memory_usage = 30 + 15 * math.sin(time.time() * 0.08)
        
        status_data = {
            **system_data,
            'motor_temperatures': motor_data['temperatures'],
            'motor_currents': motor_data['currents'],
            'motor_positions': motor_data['positions'],
            'motor_speeds': motor_data['speeds'],
            'motor_torques': motor_data['torques'],
            'motor_modes': motor_data['modes'],
            'imu_data': imu_data,
            'running_status': 'running',
            'gps_latitude': 39.9042,
            'gps_longitude': 116.4074,
            'cpu_usage': round(cpu_usage, 2),
            'memory_usage': round(memory_usage, 2),
            'updated_at': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
        }
        
        return jsonify(status_data)
    except Exception as e:
        app.logger.error(f"获取机器狗状态失败: {str(e)}")
        return jsonify({'message': f'获取状态失败: {str(e)}'}), 500

# 告警管理API
@app.route('/api/alerts', methods=['GET', 'POST'])
@auth_required
def manage_alerts(user_id):
    """获取或创建告警信息"""
    try:
        if request.method == 'GET':
            # 获取分页参数
            page = request.args.get('page', 1, type=int)
            per_page = request.args.get('per_page', 10, type=int)
            
            # 获取筛选参数
            alert_type = request.args.get('type')
            level = request.args.get('level')
            status = request.args.get('status')
            
            # 构建查询
            query = Alert.query
            
            if alert_type:
                query = query.filter(Alert.type == alert_type)
            if level:
                query = query.filter(Alert.level == level)
            if status:
                query = query.filter(Alert.status == status)
                
            # 按时间倒序排序并分页
            alerts = query.order_by(Alert.created_at.desc()).paginate(
                page=page, per_page=per_page, error_out=False
            )
            
            return jsonify({
                'alerts': [{
                    'id': alert.id,
                    'type': alert.type,
                    'level': alert.level,
                    'message': alert.message,
                    'status': alert.status,
                    'created_at': alert.created_at.strftime('%Y-%m-%d %H:%M:%S')
                } for alert in alerts.items],
                'total': alerts.total,
                'pages': alerts.pages,
                'current_page': alerts.page
            })
        else:  # POST - 创建告警
            data = request.get_json()
            if not data:
                return jsonify({'message': '没有提供数据'}), 400
                
            # 验证必须的字段
            required_fields = ['type', 'level', 'message']
            if not all(field in data for field in required_fields):
                return jsonify({'message': '缺少必要的告警信息字段'}), 400
                
            # 创建新告警
            new_alert = Alert(
                type=data['type'],
                level=data['level'],
                message=data['message'],
                status=data.get('status', 'unprocessed')
            )
            
            db.session.add(new_alert)
            db.session.commit()
            
            return jsonify({
                'message': '告警已创建',
                'alert': {
                    'id': new_alert.id,
                    'type': new_alert.type,
                    'level': new_alert.level,
                    'message': new_alert.message,
                    'status': new_alert.status,
                    'created_at': new_alert.created_at.strftime('%Y-%m-%d %H:%M:%S')
                }
            }), 201
    except Exception as e:
        db.session.rollback()
        app.logger.error(f"管理告警失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

# 更新机器人状态API
@app.route('/api/robot/status/update', methods=['POST'])
@auth_required
def update_robot_status(user_id):
    """更新机器人状态数据"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'message': '没有提供数据'}), 400
            
        # 获取最新的状态记录或创建新记录
        status = RobotStatus.query.order_by(RobotStatus.id.desc()).first()
        if not status:
            status = RobotStatus()
        
        # 更新字段
        if 'battery_level' in data:
            status.battery_level = data['battery_level']
        if 'battery_voltage' in data:
            status.battery_voltage = data['battery_voltage']
        if 'battery_current' in data:
            status.battery_current = data['battery_current']
        if 'battery_temperature' in data:
            status.battery_temperature = data['battery_temperature']
        if 'temperature' in data:
            status.temperature = data['temperature']
        if 'motor_temperatures' in data:
            status.motor_temperatures = data['motor_temperatures']
        if 'motor_currents' in data:
            status.motor_currents = data['motor_currents']
        if 'motor_positions' in data:
            status.motor_positions = data['motor_positions']
        if 'motor_speeds' in data:
            status.motor_speeds = data['motor_speeds']
        if 'motor_torques' in data:
            status.motor_torques = data['motor_torques']
        if 'motor_modes' in data:
            status.motor_modes = data['motor_modes']
        if 'imu_data' in data:
            status.imu_data = data['imu_data']
        if 'running_status' in data:
            status.running_status = data['running_status']
        if 'gps_latitude' in data:
            status.gps_latitude = data['gps_latitude']
        if 'gps_longitude' in data:
            status.gps_longitude = data['gps_longitude']
        if 'cpu_usage' in data:
            status.cpu_usage = data['cpu_usage']
        if 'memory_usage' in data:
            status.memory_usage = data['memory_usage']
        
        db.session.add(status)
        db.session.commit()
        
        return jsonify({
            'message': '机器人状态已更新',
            'status_id': status.id
        }), 200
    except Exception as e:
        db.session.rollback()
        app.logger.error(f"更新机器人状态失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

# 用户页面的运动控制和任务管理API
@app.route('/api/user/motion/control', methods=['POST'])
@auth_required
def user_motion_control(user_id):
    """用户运动控制"""
    try:
        data = request.get_json()
        required_fields = ['gait_type', 'speed', 'direction']
        
        if not all(field in data for field in required_fields):
            return jsonify({'message': '缺少必要的参数'}), 400
            
        motion = MotionControl(
            gait_type=data['gait_type'],
            speed=float(data['speed']),
            direction=data['direction']
        )
        
        db.session.add(motion)
        db.session.commit()
        
        return jsonify({
            'message': '运动控制指令已发送',
            'data': {
                'id': motion.id,
                'gait_type': motion.gait_type,
                'speed': motion.speed,
                'direction': motion.direction,
                'created_at': motion.created_at.strftime('%Y-%m-%d %H:%M:%S')
            }
        })
    except Exception as e:
        db.session.rollback()
        app.logger.error(f"发送运动控制指令失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

# 数据分析API改进
@app.route('/api/admin/analytics/overview', methods=['GET'])
@admin_required
def get_analytics_overview(user_id):
    try:
        # 获取时间范围参数
        days = request.args.get('days', 7, type=int)
        end_date = datetime.utcnow()
        start_date = end_date - timedelta(days=days)
        
        # 获取用户统计数据
        user_stats = {
            'total_users': User.query.count(),
            'active_users': User.query.filter(
                User.last_login >= (datetime.utcnow() - timedelta(days=1))
            ).count(),
            'new_users': User.query.filter(
                User.created_at >= start_date
            ).count()
        }
        
        # 获取步态数据统计
        gait_stats = {
            'total_gait_data': GaitData.query.count(),
            'normal_count': GaitData.query.filter_by(result='正常').count(),
            'abnormal_count': GaitData.query.filter_by(result='异常').count(),
            'avg_stride_length': db.session.query(db.func.avg(GaitData.stride_length)).scalar() or 0,
            'avg_step_height': db.session.query(db.func.avg(GaitData.step_height)).scalar() or 0,
            'avg_time_interval': db.session.query(db.func.avg(GaitData.time_interval)).scalar() or 0,
            'avg_point_count': db.session.query(db.func.avg(GaitData.point_count)).scalar() or 0
        }
        
        # 获取告警统计数据
        alert_stats = {
            'total_alerts': Alert.query.filter(
                Alert.created_at >= start_date
            ).count(),
            'high_priority': Alert.query.filter(
                Alert.level == 'high',
                Alert.created_at >= start_date
            ).count(),
            'unprocessed': Alert.query.filter(
                Alert.status == 'unprocessed',
                Alert.created_at >= start_date
            ).count()
        }
        
        # 获取每日趋势数据
        daily_trends = []
        current_date = start_date
        while current_date <= end_date:
            next_date = current_date + timedelta(days=1)
            daily_data = {
                'date': current_date.strftime('%Y-%m-%d'),
                'active_users': User.query.filter(
                    User.last_login.between(current_date, next_date)
                ).count(),
                'new_users': User.query.filter(
                    User.created_at.between(current_date, next_date)
                ).count(),
                'gait_data_count': GaitData.query.filter(
                    GaitData.created_at.between(current_date, next_date)
                ).count(),
                'normal_count': GaitData.query.filter(
                    GaitData.created_at.between(current_date, next_date),
                    GaitData.result == '正常'
                ).count(),
                'abnormal_count': GaitData.query.filter(
                    GaitData.created_at.between(current_date, next_date),
                    GaitData.result == '异常'
                ).count(),
                'alerts': Alert.query.filter(
                    Alert.created_at.between(current_date, next_date)
                ).count()
            }
            daily_trends.append(daily_data)
            current_date = next_date
            
        response_data = {
            'user_stats': user_stats,
            'gait_stats': gait_stats,
            'alert_stats': alert_stats,
            'daily_trends': daily_trends
        }
        
        return jsonify(response_data)
    except Exception as e:
        app.logger.error(f"获取数据分析总览失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

@app.route('/api/admin/analytics/power-consumption', methods=['GET'])
@admin_required
def get_power_consumption_analytics(user_id):
    """获取所有用户不同步态的耗电量分析"""
    try:
        # 获取最近24小时的数据
        end_time = datetime.utcnow()
        start_time = end_time - timedelta(hours=24)
        
        data = {
            'gait_types': ['trot', 'walk', 'gallop', 'jump'],
            'timestamps': [],
            'power_consumption': []
        }
        
        # 按小时统计数据
        for i in range(24):
            hour_start = end_time - timedelta(hours=i+1)
            hour_end = end_time - timedelta(hours=i)
            data['timestamps'].insert(0, hour_start.strftime('%H:00'))
            
            # 获取该小时内所有用户的步态数据
            hour_data = GaitData.query.filter(
                GaitData.created_at.between(hour_start, hour_end)
            ).all()
            
            # 计算每种步态的平均耗电量
            power_data = []
            for gait_type in data['gait_types']:
                # 这里可以根据实际情况调整耗电量计算公式
                base_power = {
                    'trot': 25,
                    'walk': 20,
                    'gallop': 30,
                    'jump': 35
                }[gait_type]
                
                # 添加一些随机变化
                variation = random.uniform(-2, 2)
                power = base_power + variation
                power_data.append(round(power, 2))
            
            data['power_consumption'].append(power_data)
        
        return jsonify(data)
    except Exception as e:
        app.logger.error(f"获取耗电量分析数据失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

@app.route('/api/admin/analytics/body-sway', methods=['GET'])
@admin_required
def get_body_sway_analytics(user_id):
    """获取所有用户不同步态的机身晃动分析"""
    try:
        # 获取最近24小时的数据
        end_time = datetime.utcnow()
        start_time = end_time - timedelta(hours=24)
        
        data = {
            'gait_types': ['trot', 'walk', 'gallop', 'jump'],
            'timestamps': [],
            'sway_data': []
        }
        
        # 按小时统计数据
        for i in range(24):
            hour_start = end_time - timedelta(hours=i+1)
            hour_end = end_time - timedelta(hours=i)
            data['timestamps'].insert(0, hour_start.strftime('%H:00'))
            
            # 获取该小时内所有用户的步态数据
            hour_data = GaitData.query.filter(
                GaitData.created_at.between(hour_start, hour_end)
            ).all()
            
            # 计算每种步态的平均晃动幅度
            sway_data = []
            for gait_type in data['gait_types']:
                # 这里可以根据实际情况调整晃动幅度计算公式
                base_sway = {
                    'trot': 2,
                    'walk': 1,
                    'gallop': 3,
                    'jump': 4
                }[gait_type]
                
                # 添加一些随机变化
                variation = random.uniform(-0.5, 0.5)
                sway = base_sway + variation
                sway_data.append(round(sway, 2))
            
            data['sway_data'].append(sway_data)
        
        return jsonify(data)
    except Exception as e:
        app.logger.error(f"获取机身晃动分析数据失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

@app.route('/api/admin/analytics/cpu-load', methods=['GET'])
@admin_required
def get_cpu_load_analytics(user_id):
    """获取所有用户的CPU负载与点位数量和轨迹长度的关系分析"""
    try:
        # 获取所有用户的步态数据
        gait_data = GaitData.query.all()
        
        data = {
            'point_counts': list(range(100, 2100, 200)),  # 点位数量范围
            'trajectory_lengths': list(range(500, 5500, 500)),  # 轨迹长度范围
            'cpu_loads': []  # CPU负载数据
        }
        
        # 生成CPU负载数据矩阵
        for point_count in data['point_counts']:
            cpu_row = []
            for length in data['trajectory_lengths']:
                # 计算该配置下的平均CPU负载
                matching_data = [d for d in gait_data if 
                               abs(d.point_count - point_count) <= 100 and 
                               abs(d.stride_length - length) <= 50]
                
                if matching_data:
                    # 基于实际数据计算负载
                    base_load = point_count / 2000 * 40 + length / 5000 * 30
                    variation = random.uniform(-5, 5)
                    cpu_load = min(100, max(0, base_load + variation))
                else:
                    # 如果没有数据，使用估算值
                    cpu_load = point_count / 2000 * 40 + length / 5000 * 30
                
                cpu_row.append(round(cpu_load, 2))
            data['cpu_loads'].append(cpu_row)
        
        return jsonify(data)
    except Exception as e:
        app.logger.error(f"获取CPU负载分析数据失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

@app.route('/api/admin/analytics/memory-usage', methods=['GET'])
@admin_required
def get_memory_usage_analytics(user_id):
    """获取所有用户的内存使用与点位数量和轨迹长度的关系分析"""
    try:
        # 获取所有用户的步态数据
        gait_data = GaitData.query.all()
        
        data = {
            'point_counts': list(range(100, 2100, 200)),  # 点位数量范围
            'trajectory_lengths': list(range(500, 5500, 500)),  # 轨迹长度范围
            'memory_usage': []  # 内存使用数据
        }
        
        # 生成内存使用数据矩阵
        for point_count in data['point_counts']:
            memory_row = []
            for length in data['trajectory_lengths']:
                # 计算该配置下的平均内存使用
                matching_data = [d for d in gait_data if 
                               abs(d.point_count - point_count) <= 100 and 
                               abs(d.stride_length - length) <= 50]
                
                if matching_data:
                    # 基于实际数据计算内存使用
                    base_usage = point_count / 2000 * 30 + length / 5000 * 20
                    variation = random.uniform(-3, 3)
                    memory_usage = min(100, max(0, base_usage + variation))
                else:
                    # 如果没有数据，使用估算值
                    memory_usage = point_count / 2000 * 30 + length / 5000 * 20
                
                memory_row.append(round(memory_usage, 2))
            data['memory_usage'].append(memory_row)
        
        return jsonify(data)
    except Exception as e:
        app.logger.error(f"获取内存使用分析数据失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

@app.route('/api/admin/analytics/motor-temperature', methods=['GET'])
@admin_required
def get_motor_temperature_analytics(user_id):
    """获取所有用户的电机温度与运行参数的关系分析"""
    try:
        # 获取所有用户的步态数据
        gait_data = GaitData.query.all()
        
        data = {
            'parameters': ['速度', '负载', '运行时间', '环境温度'],
            'values': {
                '速度': list(range(0, 55, 5)),      # 0-50 rad/s
                '负载': list(range(0, 110, 10)),    # 0-100 %
                '运行时间': list(range(0, 65, 5)),  # 0-60 min
                '环境温度': list(range(15, 41, 5))  # 15-40 °C
            },
            'temperatures': {}  # 电机温度数据
        }
        
        # 为每个参数生成温度关系数据
        for param in data['parameters']:
            temp_data = []
            for value in data['values'][param]:
                # 获取该参数值附近的数据
                matching_data = []
                if param == '速度':
                    matching_data = [d for d in gait_data if abs(d.time_interval - value/10) <= 0.1]
                elif param == '负载':
                    matching_data = [d for d in gait_data if abs(d.stride_length/5 - value) <= 5]
                elif param == '运行时间':
                    # 运行时间通过创建时间计算
                    matching_data = [d for d in gait_data if 
                                   (datetime.utcnow() - d.created_at).total_seconds()/60 <= value]
                else:  # 环境温度
                    # 使用默认温度范围
                    base_temp = value + 15
                    variation = random.uniform(-2, 2)
                    temp_data.append(round(min(85, max(20, base_temp + variation)), 2))
                    continue
                
                if matching_data:
                    # 基于实际数据计算温度
                    if param == '速度':
                        base_temp = 25 + value * 0.6
                    elif param == '负载':
                        base_temp = 25 + value * 0.4
                    elif param == '运行时间':
                        base_temp = 25 + value * 0.5
                    
                    variation = random.uniform(-2, 2)
                    temperature = min(85, max(20, base_temp + variation))
                else:
                    # 如果没有数据，使用估算值
                    temperature = 25 + value * 0.5
                
                temp_data.append(round(temperature, 2))
            
            data['temperatures'][param] = temp_data
        
        return jsonify(data)
    except Exception as e:
        app.logger.error(f"获取电机温度分析数据失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

# 添加慢速数据生成函数
def generate_slow_data():
    """在后台慢速生成告警和分析数据"""
    with app.app_context():
        while True:
            try:
                # 生成一个新的告警
                alert_types = ['系统', '电机', '电池', '传感器']
                alert_levels = ['low', 'medium', 'high']
                alert_messages = [
                    '系统温度过高',
                    '电机1温度异常',
                    '电池电量低',
                    '传感器数据异常',
                    '电机电流过大',
                    '系统内存使用率过高',
                    'CPU使用率超限',
                    '机身晃动过大'
                ]
                
                # 随机决定是否生成新告警
                if random.random() < 0.3:  # 30%的概率生成新告警
                    alert = Alert(
                        type=random.choice(alert_types),
                        level=random.choice(alert_levels),
                        message=random.choice(alert_messages),
                        status='unprocessed',
                        created_at=datetime.utcnow()
                    )
                    db.session.add(alert)
                    db.session.commit()
                    app.logger.info("生成了新的告警")

                # 生成步态数据
                if random.random() < 0.2:  # 20%的概率生成新的步态数据
                    # 获取一个随机用户
                    user = User.query.order_by(db.func.random()).first()
                    if user:
                        stride_length = random.uniform(SAFETY_RANGES['gait']['stride_length']['min'], 
                                                    SAFETY_RANGES['gait']['stride_length']['max'])
                        step_height = random.uniform(SAFETY_RANGES['gait']['step_height']['min'], 
                                                  SAFETY_RANGES['gait']['step_height']['max'])
                        time_interval = random.uniform(SAFETY_RANGES['gait']['time_interval']['min'], 
                                                    SAFETY_RANGES['gait']['time_interval']['max'])
                        point_count = random.randint(SAFETY_RANGES['gait']['point_count']['min'], 
                                                  SAFETY_RANGES['gait']['point_count']['max'])

                        gait_data = GaitData(
                            user_id=user.id,
                            task_id=random.randint(1, 100),
                            stride_length=stride_length,
                            step_height=step_height,
                            time_interval=time_interval,
                            point_count=point_count,
                            result='正常' if random.random() > 0.2 else '异常',  # 20%的概率生成异常数据
                            created_at=datetime.utcnow()
                        )
                        db.session.add(gait_data)
                        db.session.commit()
                        app.logger.info("生成了新的步态数据")

            except Exception as e:
                app.logger.error(f"生成数据时出错: {str(e)}")
                db.session.rollback()
            
            # 休眠一段时间
            time.sleep(random.uniform(30, 60))  # 每30-60秒生成一次数据

@app.route('/api/admin/safety-locks', methods=['GET', 'POST'])
@admin_required
def manage_safety_locks(user_id):
    """管理安全锁设置"""
    try:
        if request.method == 'GET':
            # 获取当前安全锁设置
            safety_lock = SafetyLock.query.order_by(SafetyLock.created_at.desc()).first()
            if not safety_lock:
                # 如果没有设置，返回默认值
                return jsonify({
                    'max_motor_temp': 45.0,
                    'max_cpu_usage': 80.0,
                    'max_memory_usage': 90.0,
                    'max_sway_angle': 30.0,
                    'min_battery_level': 20.0,
                    'max_stride_length': 100.0,
                    'max_step_height': 50.0,
                    'min_time_interval': 0.1,
                    'max_point_count': 1000
                })
            return jsonify({
                'max_motor_temp': safety_lock.max_motor_temp,
                'max_cpu_usage': safety_lock.max_cpu_usage,
                'max_memory_usage': safety_lock.max_memory_usage,
                'max_sway_angle': safety_lock.max_sway_angle,
                'min_battery_level': safety_lock.min_battery_level,
                'max_stride_length': safety_lock.max_stride_length,
                'max_step_height': safety_lock.max_step_height,
                'min_time_interval': safety_lock.min_time_interval,
                'max_point_count': safety_lock.max_point_count
            })
        else:  # POST
            data = request.get_json()
            if not data:
                return jsonify({'message': '没有提供数据'}), 400

            # 创建新的安全锁设置
            new_safety_lock = SafetyLock(
                max_motor_temp=float(data.get('max_motor_temp', 45.0)),
                max_cpu_usage=float(data.get('max_cpu_usage', 80.0)),
                max_memory_usage=float(data.get('max_memory_usage', 90.0)),
                max_sway_angle=float(data.get('max_sway_angle', 30.0)),
                min_battery_level=float(data.get('min_battery_level', 20.0)),
                max_stride_length=float(data.get('max_stride_length', 100.0)),
                max_step_height=float(data.get('max_step_height', 50.0)),
                min_time_interval=float(data.get('min_time_interval', 0.1)),
                max_point_count=int(data.get('max_point_count', 1000))
            )

            db.session.add(new_safety_lock)
            db.session.commit()
            
            app.logger.info(f"安全锁设置已更新 by user {user_id}")
            return jsonify({'message': '安全锁设置已更新'}), 200

    except Exception as e:
        db.session.rollback()
        app.logger.error(f"更新安全锁设置失败: {str(e)}")
        return jsonify({'message': f'更新安全锁设置失败: {str(e)}'}), 500

@app.route('/api/admin/motion/control', methods=['POST'])
@admin_required
def admin_motion_control(user_id):
    """管理员运动控制接口"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'message': '没有提供控制参数'}), 400

        # 验证必要的参数
        required_fields = ['gait_type', 'speed', 'direction']
        if not all(field in data for field in required_fields):
            return jsonify({'message': '缺少必要的控制参数'}), 400

        # 验证参数值的合法性
        if data['speed'] < 0 or data['speed'] > 100:
            return jsonify({'message': '速度值必须在0-100之间'}), 400

        if data['gait_type'] not in ['walk', 'run', 'jump', 'stop']:
            return jsonify({'message': '不支持的步态类型'}), 400

        if data['direction'] not in ['forward', 'backward', 'left', 'right', 'stop']:
            return jsonify({'message': '不支持的方向'}), 400

        # 创建运动控制记录
        motion = MotionControl(
            gait_type=data['gait_type'],
            speed=float(data['speed']),
            direction=data['direction']
        )
        
        db.session.add(motion)
        db.session.commit()

        # 如果是紧急停止命令，生成一条告警
        if data['gait_type'] == 'stop' or data['direction'] == 'stop':
            alert = Alert(
                type='系统',
                level='high',
                message='管理员触发紧急停止',
                status='unprocessed'
            )
            db.session.add(alert)
            db.session.commit()

        app.logger.info(f"管理员 {user_id} 发送运动控制命令: {data}")
        return jsonify({
            'message': '控制指令已发送',
            'data': {
                'gait_type': motion.gait_type,
                'speed': motion.speed,
                'direction': motion.direction,
                'timestamp': motion.created_at.strftime('%Y-%m-%d %H:%M:%S')
            }
        }), 200

    except Exception as e:
        db.session.rollback()
        app.logger.error(f"运动控制失败: {str(e)}")
        return jsonify({'message': f'运动控制失败: {str(e)}'}), 500

# 根路径处理
@app.route('/', methods=['GET'])
def index():
    """网站根路径处理函数，返回登录页面"""
    return send_file('新建文件夹/login.html')

# 添加管理员页面路由
@app.route('/admin.html', methods=['GET'])
def admin_page():
    """管理员页面"""
    return send_file('新建文件夹/admin.html')

# 添加用户页面路由
@app.route('/user.html', methods=['GET'])
def user_page():
    """用户页面"""
    return send_file('新建文件夹/user.html')

# 添加处理静态资源的路由
@app.route('/static/<path:filename>')
def serve_static(filename):
    """提供静态资源文件"""
    return send_file(f'新建文件夹/static/{filename}')

# 添加处理CSS和JS文件的路由
@app.route('/<path:filename>')
def serve_file(filename):
    """提供根目录下的其他文件，如CSS和JS"""
    if filename.endswith('.css') or filename.endswith('.js'):
        return send_file(f'新建文件夹/{filename}')
    return jsonify({'message': '请求的资源不存在'}), 404

# 添加设备绑定接口
@app.route('/api/user/device/bind', methods=['POST'])
@auth_required
def bind_device(user_id):
    """绑定设备"""
    try:
        data = request.get_json()
        if not data or 'device_id' not in data:
            return jsonify({'message': '缺少设备ID'}), 400

        device_id = data['device_id']
        
        # 检查设备是否已被绑定
        existing_binding = DeviceBinding.query.filter_by(device_id=device_id).first()
        if existing_binding:
            return jsonify({'message': '该设备已被绑定'}), 400

        # 创建新的设备绑定记录
        binding = DeviceBinding(
            user_id=user_id,
            device_id=device_id,
            bind_time=datetime.utcnow()
        )
        
        db.session.add(binding)
        db.session.commit()

        return jsonify({
            'message': '设备绑定成功',
            'data': {
                'device_id': device_id,
                'bind_time': binding.bind_time.strftime('%Y-%m-%d %H:%M:%S')
            }
        }), 200

    except Exception as e:
        db.session.rollback()
        app.logger.error(f"设备绑定失败: {str(e)}")
        return jsonify({'message': f'设备绑定失败: {str(e)}'}), 500

# 设备解绑接口
@app.route('/api/user/device/unbind/<device_id>', methods=['POST'])
@auth_required
def unbind_device(user_id, device_id):
    """解绑设备"""
    try:
        # 查找设备绑定记录
        binding = DeviceBinding.query.filter_by(
            user_id=user_id,
            device_id=device_id
        ).first()

        if not binding:
            return jsonify({'message': '未找到设备绑定记录'}), 404

        # 删除绑定记录
        db.session.delete(binding)
        db.session.commit()

        return jsonify({'message': '设备解绑成功'}), 200

    except Exception as e:
        db.session.rollback()
        app.logger.error(f"设备解绑失败: {str(e)}")
        return jsonify({'message': f'设备解绑失败: {str(e)}'}), 500

# 获取设备列表接口
@app.route('/api/user/devices', methods=['GET'])
@auth_required
def get_user_devices(user_id):
    """获取用户已绑定的设备列表"""
    try:
        # 查询用户的所有设备绑定记录
        bindings = DeviceBinding.query.filter_by(user_id=user_id).all()
        
        devices = []
        for binding in bindings:
            # 获取设备详细信息
            device = Device.query.get(binding.device_id)
            if device:
                devices.append({
                    'id': device.id,
                    'model': device.model,
                    'firmware_version': device.firmware_version,
                    'location': device.location,
                    'is_connected': device.is_connected,
                    'motor_status': device.motor_status,
                    'bind_time': binding.bind_time.strftime('%Y-%m-%d %H:%M:%S')
                })

        return jsonify({
            'message': '获取设备列表成功',
            'data': devices
        }), 200

    except Exception as e:
        app.logger.error(f"获取设备列表失败: {str(e)}")
        return jsonify({'message': f'获取设备列表失败: {str(e)}'}), 500

# 更新告警状态API
@app.route('/api/alerts/<int:alert_id>', methods=['PUT'])
@auth_required
def update_alert(user_id, alert_id):
    """更新告警状态"""
    try:
        data = request.get_json()
        alert = Alert.query.get_or_404(alert_id)
        
        if 'status' in data:
            alert.status = data['status']
            db.session.commit()
            return jsonify({'message': '告警状态更新成功'})
    except Exception as e:
        db.session.rollback()
        app.logger.error(f"更新告警状态失败: {str(e)}")
        return jsonify({'message': str(e)}), 500

if __name__ == '__main__':
    try:
        with app.app_context():
            # 检查并创建新表，不删除现有的表
            inspector = db.inspect(db.engine)
            existing_tables = inspector.get_table_names()
            
            # 检查user表是否需要更新
            if 'user' in existing_tables:
                columns = [column['name'] for column in inspector.get_columns('user')]
                if 'last_login' not in columns:
                    # 使用更兼容的方式执行SQL
                    db.session.execute(db.text("ALTER TABLE user ADD COLUMN last_login DATETIME"))
                    db.session.commit()
                    app.logger.info("Added last_login column to user table")
        
            # 创建所有必要的表（如果不存在）
            db.create_all()
            app.logger.info("数据库表检查完成")

            # 添加初始测试数据
            try:
                # 检查是否需要添加测试设备
                if not Device.query.filter_by(id="TEST001").first():
                    test_device = Device(
                        id="TEST001",
                        model="测试机器狗",
                        firmware_version="v1.0.0",
                        location="实验室",
                        is_connected=True,
                        motor_status=["normal", "normal", "normal", "normal"],
                        created_at=datetime.utcnow()
                    )
                    db.session.add(test_device)
                    db.session.commit()
                    app.logger.info("添加了测试设备")
                
                # 检查是否需要添加测试用户
                if not User.query.filter_by(username="test").first():
                    test_user = User(
                        username="test",
                        password=generate_password_hash("test123"),
                        email="test@example.com",
                        is_admin=False,
                        created_at=datetime.utcnow()
                    )
                    db.session.add(test_user)
                    db.session.commit()
                    app.logger.info("添加了测试用户")
            except Exception as e:
                db.session.rollback()
                app.logger.error(f"添加测试数据失败: {str(e)}")

            # 测试数据库连接
            try:
                # 使用更兼容的方式测试数据库连接
                db.session.execute(db.text("SELECT 1"))
                db.session.commit()
                app.logger.info("数据库连接测试成功")
            except Exception as e:
                app.logger.error(f"数据库连接测试失败: {e}")
                raise

            # 启动后台数据生成线程
            # slow_data_thread = threading.Thread(target=generate_slow_data, daemon=True)
            # slow_data_thread.start()
            # app.logger.info("后台数据生成线程已启动")

        # 启动服务器
        app.logger.info("在所有网络接口上启动服务器，端口5000...")
        app.run(host='0.0.0.0', port=5000)
        
    except Exception as e:
        app.logger.error(f"服务器启动失败: {e}")
        sys.exit(1)
    